package com.example.onlinetaxi.BaiDuMap.RoutePlan;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Overlay;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.route.DrivingRouteLine;
import com.baidu.mapapi.search.route.DrivingRouteLine.DrivingStep;
import com.example.onlinetaxi.LocalStroage.PassengerRouteLine;
import com.example.onlinetaxi.R;
import com.example.onlinetaxi.Thread.MoveCarThread;
import com.example.onlinetaxi.ui.activity.BaseActivity;
import com.example.onlinetaxi.util.BitMapUtil;
import com.example.onlinetaxi.util.ComputeUtil;

import java.util.ArrayList;
import java.util.List;

public class DrivingRouteOverlay extends OverlayManager {
    // 要绘制的路线
    private DrivingRouteLine mRouteLine = null;
    // 线程任务
    private Handler mHandler = new Handler();
    // 判断是否结束
    boolean exit = false;
    // 乘客路径中的所有点集合
    List<LatLng> latLngs = new ArrayList<>();
    // 小车移动时操作的次数
    private int mIndex;
    // 小车图标
    Marker mMoveMarker = null;
    // 小车移动的路线
    private Polyline mPolyline;
    // 灰色路线
    private List<Polyline> grayPolyLineList = new ArrayList<>();
    // 表示小车移动还没有结束
    public static Boolean carState = false;

    // 构造函数
    public DrivingRouteOverlay(BaiduMap baiduMap) {
        super(baiduMap);
    }

    // 绘制路线
    @Override
    public List<OverlayOptions> drawLine(DrivingRouteLine drivingRouteLine, String type) {
        // 路径不为空
        if (drivingRouteLine == null) {
            Log.e("route", "没有发现道路route！");
            return null;
        }
        // 获得路线
        mRouteLine = drivingRouteLine;
        // 覆盖物结果集
        List<OverlayOptions> overlayOptionses = new ArrayList<OverlayOptions>();
        // 绘制过程路线
        if (mRouteLine.getAllStep() != null && mRouteLine.getAllStep().size() > 0) {
            // 获取全部行驶路途
            List<DrivingStep> steps = mRouteLine.getAllStep();
            // 获取路数
            int stepNum = steps.size();
            // 获取路上点的经纬度
            List<LatLng> point = new ArrayList<LatLng>();
            // 获取实时交通状况
            ArrayList<Integer> traffic = new ArrayList<Integer>();
            for (int i = 0; i < stepNum; i++) {
                if (i == stepNum - 1) {
                    // 最后一步
                    point.addAll(steps.get(i).getWayPoints());
                    latLngs.addAll(steps.get(i).getWayPoints());
                } else {
                    point.addAll(steps.get(i).getWayPoints().subList(0, steps.get(i).getWayPoints().size() - 1));
                    latLngs.addAll(steps.get(i).getWayPoints().subList(0, steps.get(i).getWayPoints().size() - 1));
                }

                if (steps.get(i).getTrafficList() != null && steps.get(i).getTrafficList().length > 0) {
                    for (int j = 0; j < steps.get(i).getTrafficList().length; j++) {
                        traffic.add(steps.get(i).getTrafficList()[j]);
                    }
                }
            }

            // 用来去除路径上的间断
            Bitmap bitmap = BitmapFactory.decodeResource(BaseActivity.mContext.getResources(), R.drawable.icon_road_green_arrow);
            Bitmap bitmap_ = BitMapUtil.getResizedBitmap(bitmap, 16, 64);
            BitmapDescriptor mGreenTexture = BitmapDescriptorFactory.fromBitmap(bitmap_);

            // 设置路径选项
            PolylineOptions polylineOptions = new PolylineOptions()
                    .points(point)
                    .textureIndex(traffic)
                    .width(20)
                    .dottedLine(true)
                    .focus(true)
                    .customTexture(mGreenTexture)
                    .zIndex(0);

            // 如果是司机来接乘客的路线
            if (type.equals("driver")) {
                // 为路径添加额外信息，便于后期获得路径实体，进行路径的消除
                Bundle bundle = new Bundle();
                bundle.putString("type", type);
                polylineOptions.extraInfo(bundle);

                // 在地图上画线
                mPolyline = (Polyline) mBaiduMap.addOverlay(polylineOptions);
                // 设置经纬度
                latLngs = point;
            }

            overlayOptionses.add(polylineOptions);
        }

        return overlayOptionses;
    }

    // 绘制点
    @Override
    public List<OverlayOptions> drawPoint(DrivingRouteLine drivingRouteLine, String type) {
        // 路径不为空
        if (drivingRouteLine == null) {
            Log.e("route", "没有发现道路route！");
            return null;
        }
        // 获得路线
        mRouteLine = drivingRouteLine;
        // 覆盖物结果集
        List<OverlayOptions> overlayOptionses = new ArrayList<OverlayOptions>();

        if (type.equals("start")) {
            // 只绘制起点
            if (mRouteLine.getStarting() != null) {
                addStartMarker(overlayOptionses);
            }
        } else if (type.equals("both")) {
            // 绘制起点
            if (mRouteLine.getStarting() != null) {
                addStartMarker(overlayOptionses);
            }
            // 绘制终点
            if (mRouteLine.getTerminal() != null) {
                addTerminalMarker(overlayOptionses);
            }
        }
        // 返回覆盖物
        return overlayOptionses;
    }

    // 绘制小车并移动
    @Override
    public void drawCar() {
        // 添加小车marker
        OverlayOptions markerOptions = new MarkerOptions()
                .flat(true)
                .anchor(0.5f, 0.5f)
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.car))
                .position(latLngs.get(0))
                .rotate((float) ComputeUtil.getAngle(0, mPolyline));

        // 在地图上画小车
        mMoveMarker = (Marker) mBaiduMap.addOverlay(markerOptions);
    }

    // 用来清除已经绘制的事物
    public void clear() {
        if (MoveCarThread.moveCarThread != null) {
            // 终止绘制线程
            // 设置退出
            exit = true;
            MoveCarThread.moveCarThread = null;
        }
        if (mPolyline != null && mMoveMarker != null) {
            // 清除绘制物
            mPolyline.remove();
            mMoveMarker.remove();

            mPolyline = null;
            mMoveMarker = null;
        }
    }

    // 循环进行移动逻辑
    public void moveLooper(MapView mapView) {
        MoveCarThread.moveCarThread = new Thread() {
            public void run() {
                // 获取更精确的路线
                latLngs = divideRouteLine((ArrayList<LatLng>) latLngs);
                Thread thisThread = Thread.currentThread();
                exit = MoveCarThread.exit;

                while (!exit) {
                    for (int i = 0; i < latLngs.size() - 1; ) {
                        // 每次均为到达
                        carState = false;
                        if (exit) {
                            break;
                        }
                        for (int p = 0; p < latLngs.size() - 1; p++) {
                            // 这是更新索引的条件，这里总是为true
                            // 实际情况可以是：当前误差小于5米 DistanceUtil.getDistance(mCurrentLatLng, latLngs.get(p)) <= 5）
                            // mCurrentLatLng 这个小车的当前位置得自行获取得到
                            if (true) {
//               实际情况的索引更新 mIndex = p;
                                mIndex++; // 模拟就是每次加1
                                break;
                            }
                        }

                        // 改变循环条件
                        i = mIndex + 1;

                        // 设置退出循环
                        if (mIndex >= latLngs.size() - 1) {
                            exit = true;
                            break;
                        }

                        // 擦除走过的路线
                        mPolyline.setPoints(latLngs.subList(mIndex, latLngs.size()));

                        // 这里是小车的当前点和下一个点，用于确定车头方向
                        final LatLng startPoint = latLngs.get(mIndex);
                        final LatLng endPoint = latLngs.get(mIndex + 1);

                        // 更新小车状态
                        mMoveMarker.setPosition(startPoint);
                        mMoveMarker.setRotate((float) ComputeUtil.getAngle(startPoint, endPoint));

                        try {
                            // 控制线程更新时间间隔(1.5s)
                            thisThread.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        // 启动线程
        MoveCarThread.moveCarThread.start();
    }

    // 循环进行移动逻辑
    public void moveLooper2(MapView mapView) {
        // 用来去除路径上的间断
        Bitmap bitmap = BitmapFactory.decodeResource(BaseActivity.mContext.getResources(), R.drawable.icon_road_gray_arrow);
        Bitmap bitmap_ = BitMapUtil.getResizedBitmap(bitmap, 16, 64);
        BitmapDescriptor mGrayTexture = BitmapDescriptorFactory.fromBitmap(bitmap_);

        MoveCarThread.moveCarThread = new Thread() {
            public void run() {
                // 获取更精确的路线
                latLngs = divideRouteLine((ArrayList<LatLng>) latLngs);
                Thread thisThread = Thread.currentThread();
                exit = MoveCarThread.exit;
                while (!exit) {
                    for (int i = 0; i < latLngs.size() - 1; ) {
                        // 每次均为到达
                        carState = false;
                        if (exit) {
                            break;
                        }
                        for (int p = 0; p < latLngs.size() - 1; p++) {
                            // 这是更新索引的条件，这里总是为true
                            // 实际情况可以是：当前误差小于5米 DistanceUtil.getDistance(mCurrentLatLng, latLngs.get(p)) <= 5）
                            // mCurrentLatLng 这个小车的当前位置得自行获取得到
                            if (true) {
//               实际情况的索引更新 mIndex = p;
                                mIndex++; // 模拟就是每次加1
                                break;
                            }
                        }

                        // 改变循环条件
                        i = mIndex + 1;

                        // 设置退出循环
                        if (mIndex >= latLngs.size() - 1) {
                            exit = true;
                            break;
                        }

                        // 用来绘制灰绿相间的路线
                        PolylineOptions polylineOptions = null;
                        if (mIndex + 2 < latLngs.size() - 1) {
                            // 添加一条灰色路线（表示已经走过）
                            polylineOptions = new PolylineOptions()
                                    .points(latLngs.subList(0, mIndex + 2))
                                    .width(20)
                                    .dottedLine(true)
                                    .focus(true)
                                    .customTexture(mGrayTexture)
                                    .zIndex(-1);
                        }
                        Polyline grayPolyLine = (Polyline) mBaiduMap.addOverlay(polylineOptions);
                        if (grayPolyLine != null) {
                            grayPolyLineList.add(grayPolyLine);
                        }

                        // 只保留一条灰色路线，不要每次都画一条
                        if (grayPolyLineList.size() > 1) {
                            for (Polyline polyline : grayPolyLineList.subList(0, grayPolyLineList.size() - 1)) {
                                polyline.remove();
                            }
                            grayPolyLineList.clear();
                            grayPolyLineList.add(grayPolyLine);
                        }

                        // 绘制将要途径的路线
                        mPolyline.setPoints(latLngs.subList(mIndex - 1, latLngs.size()));


                        // 这里是小车的当前点和下一个点，用于确定车头方向
                        final LatLng startPoint = latLngs.get(mIndex);
                        final LatLng endPoint = latLngs.get(mIndex + 1);

                        // 更新小车状态
                        // 更新小车的位置和车头的角度
                        mMoveMarker.setPosition(startPoint);
                        mMoveMarker.setRotate((float) ComputeUtil.getAngle(startPoint, endPoint));

                        try {
                            // 控制线程更新时间间隔(1.5s)
                            thisThread.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        // 启动线程
        MoveCarThread.moveCarThread.start();
    }

    // 截取后的路线点的结果集（使得小车可以平滑移动）
    private List<LatLng> divideRouteLine(List<LatLng> routeline) {
        ArrayList<LatLng> result = new ArrayList<>();
        for (int i = 0; i < routeline.size() - 1; i++) {
            final LatLng startpoint = routeline.get(i);
            final LatLng endpoint = routeline.get(i + 1);
            double slope = ComputeUtil.getSlope(startpoint, endpoint);
            // 是不是正向的标示
            boolean isyreverse = (startpoint.latitude > endpoint.latitude);
            boolean isxreverse = (startpoint.longitude > endpoint.longitude);
            double intercept = ComputeUtil.getInterception(slope, startpoint);
            double xmovedistance = isxreverse ? ComputeUtil.getXMoveDistance(slope) :
                    -1 * ComputeUtil.getXMoveDistance(slope);
            double ymovedistance = isyreverse ? ComputeUtil.getYMoveDistance(slope) :
                    -1 * ComputeUtil.getYMoveDistance(slope);
            ArrayList<LatLng> temp1 = new ArrayList<>();
            for (double j = startpoint.latitude, k = startpoint.longitude;
                 !((j > endpoint.latitude) ^ isyreverse) && !((k > endpoint.longitude) ^ isxreverse); ) {
                LatLng latlng = null;
                if (slope == Double.MAX_VALUE) {
                    latlng = new LatLng(j, k);
                    j = j - ymovedistance;
                } else if (slope == 0.0) {
                    latlng = new LatLng(j, k - xmovedistance);
                    k = k - xmovedistance;
                } else {
                    latlng = new LatLng(j, (j - intercept) / slope);
                    j = j - ymovedistance;
                }
                final LatLng finallatlng = latlng;
                if (finallatlng.latitude == 0 && finallatlng.longitude == 0) {
                    continue;
                }
                temp1.add(finallatlng);
            }
            result.addAll(temp1);
            if (i == routeline.size() - 2) {
                result.add(endpoint); // 终点
            }
        }
        return result;
    }

    // 设置起点图标
    private void addStartMarker(List<OverlayOptions> overlayOptionses) {
        OverlayOptions overlayOptions = (new MarkerOptions())
                .position(mRouteLine.getStarting().getLocation())
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_start))
                .zIndex(10);

//        overlayOptionses.add();
        Marker marker = (Marker) mBaiduMap.addOverlay(overlayOptions);
        PassengerRouteLine.overlays.add(marker);
    }

    // 设置终点图标
    private void addTerminalMarker(List<OverlayOptions> overlayOptionses) {
        OverlayOptions overlayOptions = (new MarkerOptions())
                .position(mRouteLine.getTerminal().getLocation())
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_end))
                .zIndex(10);
//        overlayOptionses.add();
        Marker marker = (Marker) mBaiduMap.addOverlay(overlayOptions);
        PassengerRouteLine.overlays.add(marker);
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        return false;
    }

    @Override
    public boolean onPolylineClick(Polyline polyline) {
        return false;
    }
}
